// Copyright Gary Evans 2006-2007.

using System;
using System.Collections.Generic;
using System.Text;

using Taumuon.Jabuka.Physics;
using Collision = Taumuon.Jabuka.Physics.Collision;

namespace Taumuon.Jabuka.MainApp
{
    /// <summary>
    /// Lots of spheres colliding with a large immovable sphere.
    /// </summary>
    [Scene("4. Lots of spheres", "Lots of spheres colliding with a large immovable sphere.")]
    public class Scene4 : BaseScene
    {
        #region Overrides

        /// <summary>
        /// Resets the Scene to its starting point.
        /// </summary>
        public override void ResetScene()
        {
            List<Collision.Sphere> spheres = new List<Collision.Sphere>();
            drawableObjects = new List<IDrawable>();

            #region Grid Of Spheres

            // Draws spheres arranged in a 'grid'.
            const int numberSpheresPerSide = 12;
            const double radius = 5.0;
            const double separationBetweenSpheres = 2.0;

            // the centre of the grid.
            const double xCentre = 0.0;
            const double zCentre = -120.0;

            // The y plane that the grid lies in.
            double yLocation = 30.0;

            double initialX = xCentre - (((numberSpheresPerSide - 1) * ((radius * 2.0) + separationBetweenSpheres)) / 2.0) - (separationBetweenSpheres / 2.0);
            double initialZ = zCentre - (((numberSpheresPerSide - 1) * ((radius * 2.0) + separationBetweenSpheres)) / 2.0) - (separationBetweenSpheres / 2.0);

            for (int x = 0; x < numberSpheresPerSide; ++x)
            {
                for (int z = 0; z < numberSpheresPerSide; ++z)
                {
                    EulerRigidBody sphereRigidBody = new EulerRigidBody(
                        new Vector(initialX + (x * ((radius * 2) + separationBetweenSpheres)),
                                    yLocation,
                                    initialZ + (z * ((radius * 2) + separationBetweenSpheres)))
                        , new Vector(), 1.0);
                    Collision.Sphere sphere = new Collision.Sphere(sphereRigidBody, radius);
                    spheres.Add(sphere);
                    drawableObjects.Add(new Sphere(sphereRigidBody, radius, new Colour(0.0f, 1.0f, 0.0f)));
                    sphereRigidBody.ApplyForce(new Vector(0.0, -1.0, 0.0));
                }
            }

            #endregion Grid Of Spheres

            #region Big Sphere

            double radiusBigYLocation = 10; // the y offset for the big sphere
            double radiusBig = 100.0;
            EulerRigidBody sphereBigRigidBody = new EulerRigidBody(
                new Vector(xCentre, -radiusBig + radiusBigYLocation, zCentre), new Vector(), double.PositiveInfinity);
            Collision.Sphere bigSphere = new Collision.Sphere(sphereBigRigidBody, radiusBig);
            spheres.Add(bigSphere);
            drawableObjects.Add(new Sphere(sphereBigRigidBody, radiusBig, new Colour(0.0f, 0.0f, 1.0f)));

            #endregion Big Sphere

            this.collisionManager = new Collision.CollisionManager(spheres);
        }

        /// <summary>
        /// This should return an array containing 4 entries - the parameters
        ///  to pass into Gl.glrotated (i.e. angle in degrees, then the 3
        ///  values specifying the rotation vector.
        /// If null is returned (or an array of any other size), then no rotation
        ///  occurs.
        /// </summary>
        /// <remarks>
        /// A nasty hack! This will be removed once we include a camera class.
        /// If this returns non-null, then the scene will be rotated.
        /// </remarks>
        public override double[] CameraRotation
        {
            get
            {
                return new double[] { 30.0, 1.0, 0.0, 0.0 };
            }
        }

        #endregion Overrides
    }
}
